home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1994 / MacHack 1994.toast / MacHack™94 / Talks & Papers / Michael D. Crawford↵ / Word Services SDK 1.0.5 / Writeswell Jr. Source / Prefs.c < prev    next >
Text File  |  1992-12-29  |  13KB  |  668 lines

  1. /* Prefs.c
  2.  * Preferences file management
  3.  * ©1992 Working Software, Inc.
  4.  * This source code is copyrighted.  Permission is granted to use the Word Services
  5.  * portion of the Writeswell Jr. source code in your own programs, but you 
  6.  * may not distribute the Writeswell Jr. word-processor code as a 
  7.  * commercial product.  If you modify the code, please do not call it 
  8.  * Writeswell Jr. (or Writeswell.)  This will ensure that people understand the 
  9.  * program and don’t have to deal with a number of different versions with 
  10.  * who-knows-what going on in the code.
  11.  * 
  12.  * Writeswell Jr. and Writeswell are trademarks of Working Software, Inc.
  13.  * 18 Apr 92 Mike Crawford
  14.  */
  15.  
  16. #include <EPPC.h>
  17. #include <AppleEvents.h>
  18. #include <AEObjects.h>
  19. #include <Folders.h>
  20. #include <Aliases.h>
  21. #include "AERegistry.h"
  22. #include "TBConstants.h"
  23. #include "TBGlobals.h"
  24. #include "Prefs.h"
  25. #include "MyGestalt.h"
  26. #include "MyFolders.h"
  27. #include "Gripe.h"
  28.  
  29. #define kAFServiceBaseID    2000
  30. #define kAFMenuIconBaseID    1257
  31.  
  32.  
  33. Boolean OpenPrefFile( void )
  34. {
  35.     short            oldDrive;
  36.     long            oldDir;
  37.     OSErr            err;
  38.     short            vRef;
  39.     long            dirID;
  40.     WDParam            wPB;
  41.     short            curFile;
  42.     Str255            prefsFileName;
  43.  
  44.     /* Find the preferences folder */
  45.     
  46.     if ( GetPrefFolder( &vRef, &dirID ) )
  47.         return false;
  48.     
  49.     /* Check if file exists */
  50.     
  51.     GetIndString( prefsFileName, kMiscStringID, kPreferencesFileNameStr );
  52.     
  53.     if ( prefsFileName[0] == '\0' )
  54.         return false;
  55.  
  56.     if ( !FileExistsWithThisType( vRef, dirID, prefsFileName, 'pref' ) ){
  57.     
  58.         /* if not, create it with default prefs */
  59.         if ( !CreateDefaultPrefFile( vRef, dirID, prefsFileName ) )
  60.             return false;
  61.     }    
  62.  
  63.     /* otherwise, open the file */
  64.     
  65.     wPB.ioCompletion = 0;
  66.     wPB.ioNamePtr = (StringPtr)NULL;
  67.     
  68.     err = PBHGetVol( &wPB, false );
  69.     if ( err )
  70.         return false;
  71.     
  72.     oldDrive = wPB.ioWDVRefNum;
  73.     oldDir = wPB.ioWDDirID;
  74.  
  75.     wPB.ioVRefNum = vRef;
  76.     wPB.ioWDDirID = dirID;
  77.     wPB.ioNamePtr = (StringPtr)NULL;
  78.         
  79.     err = PBHSetVol( &wPB, false );
  80.     if ( err )
  81.         return false;
  82.     
  83.     curFile = CurResFile();
  84.  
  85.     gPrefFileRefNum = OpenResFile( prefsFileName );
  86.     
  87.     err = ResError();
  88.  
  89.     UseResFile( curFile );            /* Restore old res file */
  90.  
  91.     wPB.ioVRefNum = oldDrive;
  92.     wPB.ioWDDirID = oldDir;
  93.  
  94.     err = PBHSetVol( &wPB, false );            /* Restore original volume */
  95.  
  96.     if ( gPrefFileRefNum == -1 || err ){
  97.         return false;
  98.     }
  99.  
  100.     if ( ValidatePrefsFile() )
  101.         return false;
  102.  
  103.     return true;
  104. }
  105.  
  106. OSErr ValidatePrefsFile( void )
  107. {
  108.     short    curFile;
  109.     short    i;
  110.     OSErr    err;
  111.     Handle    h;
  112.  
  113.     curFile = CurResFile();
  114.     UseResFile( gPrefFileRefNum );
  115.  
  116.     /* Get defaults out of the application */
  117.     
  118.     if ( !( h = Get1Resource( 'PreF', kPFPrefsID )) ){
  119.         if ( err = CopyResource( kAFPrefsID, kPFPrefsID, 'PreF', gAppFileRefNum, gPrefFileRefNum  )){
  120.             UseResFile( curFile );
  121.             return err;
  122.         }
  123.  
  124. #ifdef __DEMO__
  125.  
  126.         /* Pre-install Spellswell in the menu
  127.          * 1.0.2 MDC I put this inside the if Get1Resource statement
  128.          */
  129.     
  130.         if ( System7Installed() ){
  131.             if ( err = AddSpellerItem() ){
  132.                 UseResFile( curFile );
  133.                 return err;
  134.             }
  135.         }    
  136. #endif
  137.  
  138.     }
  139.  
  140.     UpdateResFile( gPrefFileRefNum );
  141.     
  142.     UseResFile( curFile );    
  143.     
  144.     err = ResError();
  145.     
  146.     return err;
  147. }
  148.  
  149. #ifdef __DEMO__
  150.  
  151. OSErr AddSpellerItem( void )
  152. {
  153.     OSErr            err;
  154.     FSSpec            spellerSpec;
  155.     Boolean            foundSpeller;
  156.     Handle            h;
  157.     WWJrPrefsHdl    prefHdl;
  158.  
  159.     /* We want to show the menu already installed for the demo disks */
  160.  
  161.     if ( err = LookForSpeller( &spellerSpec, &foundSpeller ) )
  162.         return err;
  163.     
  164.     if ( !foundSpeller )
  165.         return noErr;        /* No error - speller was just not there */
  166.  
  167.     if ( !( h = Get1Resource( rAliasType, kServiceBaseID )) )
  168.         if ( err = CopyResource( kAFServiceBaseID, kServiceBaseID, rAliasType, gAppFileRefNum, gPrefFileRefNum  )){
  169.             return err;
  170.         }
  171.  
  172.     if ( err = PointAliasAtSpeller( kServiceBaseID, &spellerSpec ) ){
  173.         return err;
  174.     }
  175.  
  176.     if ( !( h = Get1Resource( 'STR ', kServiceBaseID )) )
  177.         if ( err = CopyResource( kAFServiceBaseID, kServiceBaseID, 'STR ', gAppFileRefNum, gPrefFileRefNum  )){
  178.             return err;
  179.         }
  180.  
  181.     if ( !( h = Get1Resource( 'SICN', kMenuIconBaseID )) )
  182.         if ( err = CopyResource( kAFMenuIconBaseID, kMenuIconBaseID, 'SICN', gAppFileRefNum, gPrefFileRefNum  )){
  183.             return err;
  184.         }
  185.  
  186.     prefHdl = GetPrefHandle();
  187.     if ( !prefHdl ){
  188.         Gripe( "\pCannot get preferences handle" );
  189.         return resNotFound;
  190.     }
  191.  
  192.     (*prefHdl)->serviceType[ 0 ] = kBatchService;
  193.     
  194.     ChangedResource( prefHdl );
  195.     WriteResource( prefHdl );
  196.     
  197.     return noErr;
  198. }
  199.  
  200. OSErr LookForSpeller( FSSpec *spellSpecPtr, Boolean *foundPtr )
  201. {
  202.     OSErr        err;
  203.     short        vRef;
  204.     long        dirID;
  205.     CInfoPBRec    cPB;
  206.     Str255        fileName;
  207.     short        dirIndex;
  208.  
  209.     *foundPtr = false;
  210.     
  211.     err = GetMyFolder( &vRef, &dirID );
  212.     if ( err )
  213.         return err;
  214.     
  215.     /* Now we search for the speller by creator code and type, by indexing through
  216.      * the folder's contents.
  217.      */
  218.     
  219.     dirIndex = 0;
  220.  
  221.     do {
  222.     
  223.         dirIndex++;
  224.  
  225.         cPB.hFileInfo.ioCompletion = (ProcPtr)NULL;
  226.         cPB.hFileInfo.ioNamePtr = fileName;
  227.         cPB.hFileInfo.ioVRefNum = vRef;
  228.         cPB.hFileInfo.ioFDirIndex = dirIndex;
  229.         cPB.hFileInfo.ioDirID = dirID;
  230.         
  231.         err = PBGetCatInfo( &cPB, false );
  232.         
  233.         if ( err && err != fnfErr )
  234.             return err;
  235.         
  236.         if ( cPB.dirInfo.ioFlAttrib & 0x10 )
  237.             continue;                            /* It's a directory */
  238.         
  239.         if ( cPB.hFileInfo.ioFlFndrInfo.fdType == 'APPL' ){
  240.             if ( cPB.hFileInfo.ioFlFndrInfo.fdCreator == 'SPWE' ){
  241.             
  242.                 /* We've got the speller.  Create the FSSpec for it */
  243.                 
  244.                 err = FSMakeFSSpec( vRef,
  245.                                     dirID,
  246.                                     fileName,
  247.                                     spellSpecPtr );
  248.                 
  249.                 if ( !err )
  250.                     *foundPtr = true;
  251.  
  252.                 return err;
  253.             }
  254.         }
  255.         
  256.         
  257.     } while ( err != fnfErr );
  258.     
  259.     /* If we get here, then the speller is simply not present */
  260.  
  261.     return noErr;
  262. }
  263.  
  264. OSErr GetMyFolder( short *vRefPtr, long *dirIDPtr )
  265. {
  266.     Handle        codeHdl;
  267.     short        appRefNum;
  268.     FCBPBRec    pb;
  269.     FSSpec        fSpec;
  270.     OSErr        err;
  271.     Str255        fileName;
  272.  
  273.     /* Find out our resource file refNum */
  274.     
  275.     codeHdl = GetResource( 'CODE', 0 );        /* Get a resource from our res file */
  276.     
  277.     if ( !codeHdl )
  278.         return resNotFound;
  279.     
  280.     appRefNum = HomeResFile( codeHdl );
  281.     
  282.     pb.ioCompletion = (ProcPtr)NULL;
  283.     pb.ioRefNum = appRefNum;
  284.     pb.ioVRefNum = 0;
  285.     pb.ioFCBIndx = 0;
  286.     pb.ioNamePtr = fileName;
  287.  
  288.     err = PBGetFCBInfo( &pb, false );
  289.     
  290.     if ( err ){
  291.         Gripe( "\pGetFCBInfo failed" );
  292.         return err;
  293.     }
  294.  
  295.     *vRefPtr = pb.ioVRefNum;
  296.     *dirIDPtr = pb.ioFCBParID;
  297.  
  298.     return noErr;
  299. }
  300.  
  301. OSErr PointAliasAtSpeller( short aliasID, const FSSpecPtr spellerSpecPtr )
  302. {
  303.     OSErr        err;
  304.     AliasHandle    oldAliasHdl;
  305.     Boolean        wasChanged;
  306.  
  307.     /* Get an existing alias from the preferences file, and "aim" it at
  308.      * Spellswell 7, which is given by the spellerSpecPtr.
  309.      * This allows the demo to be run off of locked demo disks and CD's, without
  310.      * having to set up the alias record ahead of time.
  311.      */
  312.     
  313.     oldAliasHdl = (AliasHandle)GetResource( rAliasType, aliasID );
  314.     if ( !oldAliasHdl )
  315.         return resNotFound;
  316.  
  317.     err = UpdateAlias( (FSSpecPtr)NULL, spellerSpecPtr, oldAliasHdl, &wasChanged );
  318.     if ( err ){
  319.         Gripe( "\pUpdateAlias failed" );
  320.         return err;
  321.     }
  322.     
  323.     (*oldAliasHdl)->userType = 'SPWE';            /* Put creator into alias record */
  324.     
  325.     ChangedResource( oldAliasHdl );
  326.     WriteResource( oldAliasHdl );
  327.     
  328.     return noErr;
  329. }
  330. #endif
  331.  
  332. OSErr GetPrefFolder( short *vRefPtr, long *dirIDPtr )
  333. {
  334.     OSErr    errCode;
  335.     long    blessedID;
  336.  
  337.     if ( FindFolderPresent() ){
  338.         errCode = FindFolder( kOnSystemDisk,
  339.                             kPreferencesFolderType,
  340.                             true,
  341.                             vRefPtr,
  342.                             dirIDPtr );
  343.         return errCode;
  344.     }
  345.     
  346.     /* System 6 style */
  347.  
  348.     /* First, get the refNum of the boot drive, and the ID of the system folder */
  349.     
  350.     errCode = GetSysVolID( vRefPtr, &blessedID );
  351.     if ( errCode ){
  352.         return errCode;
  353.     }
  354.     
  355.     /* Now get the ID of the "Preferences" folder in the system folder.
  356.      * if it does not exist, create it. */
  357.     
  358.     errCode = FindDirectory( *vRefPtr, blessedID, "\pPreferences", dirIDPtr );
  359.     if ( errCode == dirNFErr ){
  360.             errCode = MakeFolder( dirIDPtr, *vRefPtr, blessedID, "\pPreferences" );
  361.             if ( errCode )
  362.                 return errCode;
  363.     } else if ( errCode ){
  364.             return errCode;
  365.     }
  366.     
  367.     return noErr;
  368. }
  369.  
  370. Boolean FileExistsWithThisType( short vRef, long dirID, StringPtr fileName, OSType type )
  371. {
  372.     OSErr            err;
  373.     HParmBlkPtr        pbPtr;
  374.     Boolean            result;
  375.     long            oldSize;
  376.     
  377.     pbPtr = (HParmBlkPtr)NewPtr( sizeof( HParamBlockRec ) );
  378.  
  379.     if ( !pbPtr )
  380.         return false;
  381.         
  382.     pbPtr->fileParam.ioCompletion = (ProcPtr)NULL;
  383.     pbPtr->fileParam.ioDirID = dirID;
  384.     pbPtr->fileParam.ioNamePtr = fileName;
  385.     pbPtr->fileParam.ioVRefNum = vRef;
  386.     pbPtr->fileParam.ioFDirIndex = 0;
  387.     
  388.     err = PBHGetFInfo( pbPtr, false );
  389.     
  390.     if ( err ){
  391.         result = false;
  392.     } else {
  393.     
  394.         if ( pbPtr->fileParam.ioFlFndrInfo.fdType != type )
  395.             result = false;
  396.         else
  397.             result = true;
  398.     }
  399.     
  400.     DisposPtr( pbPtr );
  401.     return result;
  402. }
  403.  
  404. Boolean CreateDefaultPrefFile( short vRef, long dirID, StringPtr fileName )
  405. {
  406.     OSErr            err;
  407.     HParmBlkPtr        pbPtr;
  408.     Boolean            result;
  409.     short            wdRef;
  410.     long            oldDir;
  411.     short            oldVol;
  412.     long            oldSize;
  413.  
  414.     /* We cannot count on the presence of HCreateResFile */
  415.  
  416.     
  417.     pbPtr = (HParmBlkPtr)NewPtr( sizeof( HParamBlockRec ) );
  418.     
  419.     if ( !pbPtr )
  420.         return false;
  421.     
  422.     pbPtr->wdParam.ioCompletion = (ProcPtr)NULL;
  423.     pbPtr->wdParam.ioWDDirID = dirID;
  424.     pbPtr->wdParam.ioNamePtr = (StringPtr)NULL;
  425.     pbPtr->wdParam.ioVRefNum = vRef;
  426.     pbPtr->wdParam.ioWDProcID = 'ERIK';
  427.     
  428.     err = PBOpenWD( pbPtr, false );
  429.  
  430.     if ( err ){
  431.         DisposPtr( pbPtr );
  432.         return false;
  433.     }
  434.     
  435.     wdRef = pbPtr->wdParam.ioVRefNum;
  436.     
  437.     pbPtr->wdParam.ioCompletion = (ProcPtr)NULL;
  438.  
  439.     err = PBHGetVol( pbPtr, false );
  440.     
  441.     if ( err ){
  442.         DisposPtr(  pbPtr );
  443.         return false;
  444.     }
  445.     
  446.     oldDir = pbPtr->wdParam.ioWDDirID;
  447.     oldVol = pbPtr->wdParam.ioWDVRefNum;
  448.     
  449.     ((ParmBlkPtr)pbPtr)->fileParam.ioCompletion = (ProcPtr)NULL;
  450.     ((ParmBlkPtr)pbPtr)->fileParam.ioNamePtr = (StringPtr)NULL;
  451.     ((ParmBlkPtr)pbPtr)->fileParam.ioVRefNum = wdRef;
  452.     
  453.     err = PBSetVol( pbPtr, false );
  454.  
  455.     if ( err ){
  456.         DisposPtr( pbPtr );
  457.         return false;
  458.     }
  459.     
  460.     CreateResFile( fileName );
  461.     
  462.     err = ResError();
  463.     
  464.     if ( err ){
  465.         DisposPtr( pbPtr );
  466.         return false;
  467.     }
  468.  
  469.     pbPtr->fileParam.ioCompletion = (ProcPtr)NULL;
  470.     pbPtr->fileParam.ioDirID = dirID;
  471.     pbPtr->fileParam.ioNamePtr = fileName;
  472.     pbPtr->fileParam.ioVRefNum = vRef;
  473.     pbPtr->fileParam.ioFDirIndex = 0;
  474.     
  475.     err = PBHGetFInfo( pbPtr, false );
  476.     
  477.     if ( err ){
  478.         DisposPtr( pbPtr );
  479.         return false;
  480.     }
  481.  
  482.     pbPtr->fileParam.ioFlFndrInfo.fdType = 'pref';
  483.     pbPtr->fileParam.ioFlFndrInfo.fdCreator = 'MiKe';
  484.     pbPtr->fileParam.ioDirID = dirID;
  485.     pbPtr->fileParam.ioNamePtr = fileName;
  486.     pbPtr->fileParam.ioVRefNum = vRef;
  487.     pbPtr->fileParam.ioFDirIndex = 0;
  488.     
  489.     err = PBHSetFInfo( pbPtr, false );
  490.     
  491.     if ( err ){
  492.         DisposPtr( pbPtr );
  493.         return false;
  494.     }
  495.     
  496.     pbPtr->wdParam.ioCompletion = (ProcPtr)NULL;
  497.     pbPtr->wdParam.ioWDDirID = oldDir;
  498.     pbPtr->wdParam.ioNamePtr = (StringPtr)NULL;
  499.     pbPtr->wdParam.ioVRefNum = oldVol;
  500.  
  501.     err = PBHSetVol( pbPtr, false );
  502.  
  503.     if ( err ){
  504.         DisposPtr( pbPtr );
  505.         return false;
  506.     }
  507.  
  508.     pbPtr->wdParam.ioCompletion = (ProcPtr)NULL;
  509.     pbPtr->wdParam.ioVRefNum = wdRef;
  510.     
  511.     err = PBCloseWD( pbPtr, false );
  512.     
  513.     DisposPtr( pbPtr );
  514.     
  515.     if ( err )
  516.         return false;
  517.     
  518.     return true;
  519. }
  520.  
  521. OSErr CopyResource( short fromID,
  522.                     short toID,
  523.                     ResType theType,
  524.                     short fromFile,
  525.                     short toFile )
  526. {
  527.     short    curFile;
  528.     Handle    h;
  529.     Str255    name;
  530.     short    attr;
  531.     ResType    myType;
  532.     short    myID;
  533.     OSErr    err;
  534.     
  535.     /* This function will not work correctly if the ChangedResource
  536.      * or purge bits are set.
  537.      */
  538.     curFile = CurResFile();
  539.     UseResFile( fromFile );
  540.     
  541.     if ( err = ResError() ){
  542.         return err;
  543.     }
  544.     
  545.     h = GetResource( theType, fromID );
  546.     
  547.     UseResFile( curFile );
  548.     
  549.     if ( err || (err = ResError()) ){
  550.         return err;
  551.     }
  552.     
  553.     if ( !h || !*h ){
  554.         return resNotFound;
  555.     }
  556.     
  557.     GetResInfo( h, &myID, &myType, name );
  558.     if ( err = ResError() ){
  559.         return err;
  560.     }
  561.     attr = GetResAttrs( h );
  562.     if ( err = ResError() ){
  563.         return err;
  564.     }
  565.     
  566.     DetachResource( h );
  567.     if ( err = ResError() ){
  568.         return err;
  569.     }
  570.     
  571.     curFile = CurResFile();
  572.     UseResFile( toFile );
  573.  
  574.     AddResource( h, theType, toID, name );
  575.     if ( err = ResError() ){
  576.         UseResFile( curFile );
  577.         return err;
  578.     }
  579.  
  580.     WriteResource( h );
  581.     if ( err = ResError() ){
  582.         UseResFile( curFile );
  583.         return err;
  584.     }
  585.     
  586.     UseResFile( curFile );
  587.  
  588.     if ( err = ResError() ){
  589.         return err;
  590.     }
  591.     
  592.     SetResAttrs( h, attr );
  593.     if ( err = ResError() ){
  594.         return err;
  595.     }
  596.     
  597.  
  598.     return noErr;
  599. }
  600.  
  601. #ifdef NEVER                        /* This will return in a future version */
  602. void ToggleSelectCheck( void )
  603. {
  604.     WWJrPrefsHdl    prefHdl;
  605.     
  606.     prefHdl = GetPrefHandle();
  607.     if ( !prefHdl ){
  608.         Gripe( "\pCannot get preferences handle" );
  609.         return;
  610.     }
  611.  
  612.     if ( (*prefHdl)->checkSel ){
  613.         (*prefHdl)->checkSel = 0;
  614.     }else{
  615.         (*prefHdl)->checkSel = 1;
  616.     }
  617.  
  618.     ChangedResource( prefHdl );
  619.     WriteResource( prefHdl );
  620.  
  621.     CheckSelectMenu( prefHdl );
  622.  
  623.     return;
  624. }
  625.  
  626. void CheckSelectMenu( WWJrPrefsHdl prefHdl )
  627. {
  628.     MenuHandle    servMenu;
  629.  
  630.     servMenu = GetServiceMenu();
  631.     if ( !servMenu ){
  632.         Gripe( "\pCannot get service menu handle" );
  633.         return;
  634.     }
  635.  
  636.     if ( (*prefHdl)->checkSel ){
  637.         CheckItem( servMenu, kSMCheckSel, true );
  638.     }else{
  639.         CheckItem( servMenu, kSMCheckSel, false );
  640.     }
  641.  
  642.     return;
  643. }
  644. #endif
  645.  
  646. MenuHandle GetServiceMenu( void )
  647. {
  648.     MenuHandle servMenu;
  649.     
  650.     servMenu = (MenuHandle)GetResource( 'MENU', kServMenuID );
  651.     
  652.     return servMenu;
  653. }
  654.  
  655. WWJrPrefsHdl GetPrefHandle( void )
  656. {
  657.     WWJrPrefsHdl    prefHdl;
  658.     short            curFile;
  659.     
  660.     curFile = CurResFile();
  661.     UseResFile( gPrefFileRefNum );
  662.     
  663.     prefHdl = (WWJrPrefsHdl)GetResource( 'PreF', kPFPrefsID );
  664.     
  665.     UseResFile( curFile );
  666.  
  667.     return prefHdl;                    /* Might be Nil; up to caller to check */
  668. }